#include "gpio_led.h"

TIM_HandleTypeDef htimx;
/* LED亮度,PWM表指数曲线*/
uint16_t indexWave[] =
{
    1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
    2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
    6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 12,
    12, 13, 14, 15, 17, 18, 19, 20, 22,
    23, 25, 27, 29, 31, 33, 36, 38, 41,
    44, 47, 51, 54, 58, 63, 67, 72, 77,
    83, 89, 95, 102, 110, 117, 126, 135,
    145, 156, 167, 179, 192, 206, 221, 237,
    254, 272, 292, 313, 336, 361, 387, 415,
    445, 477, 512, 512, 477, 445, 415, 387,
    361, 336, 313, 292, 272, 254, 237, 221,
    206, 192, 179, 167, 156, 145, 135, 126,
    117, 110, 102, 95, 89, 83, 77, 72, 67, 63,
    58, 54, 51, 47, 44, 41, 38, 36, 33, 31, 29,
    27, 25, 23, 22, 20, 19, 18, 17, 15, 14, 13,
    12, 12, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5,
    5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
    2, 2, 1, 1, 1, 1, 1, 1
};
/*********SPWM 实验的正弦曲线表*************/  
/* SPWM 表,正弦曲线，此表使用工程目录下的 python 脚本 sin_wave.py 生成*/  
const uint16_t indexSpwm[] = {  
    0, 9, 18, 27, 36, 45, 54, 63, 72, 81, 89, 98,  
    107, 116, 125, 133, 142, 151, 159, 168, 176,  
    184, 193, 201, 209, 218, 226, 234, 242, 249,  
    257, 265, 273, 280, 288, 295, 302, 310, 317,  
    324, 331, 337, 344, 351, 357, 364, 370, 376,  
    382, 388, 394, 399, 405, 410, 416, 421, 426,  
    431, 436, 440, 445, 449, 454, 458, 462, 465,  
    469, 473, 476, 479, 482, 485, 488, 491, 493,  
    496, 498, 500, 502, 503, 505, 506, 508, 509,  
    510, 510, 511, 512, 512, 512, 512, 512, 512,  
    511, 510, 510, 509, 508, 506, 505, 503, 502,  
    500, 498, 496, 493, 491, 488, 485, 482, 479,  
    476, 473, 469, 465, 462, 458, 454, 449, 445,  
    440, 436, 431, 426, 421, 416, 410, 405, 399,  
    394, 388, 382, 376, 370, 364, 357, 351, 344,  
    337, 331, 324,  317, 310, 302, 295, 288, 280,  
    273, 265, 257, 249, 242, 234, 226, 218, 209,  
    201, 193, 184, 176, 168, 159, 151, 142, 133,  
    125, 116, 107, 98, 89, 81, 72, 63, 54, 45, 36,  
    27, 18, 9, 0  
};  

int rt_hw_gpio_led_init(void)
{
    rt_pin_mode(LEDR_PIN, PIN_MODE_OUTPUT_NOPULL);
    rt_pin_mode(LEDG_PIN, PIN_MODE_OUTPUT_NOPULL);
    rt_pin_mode(LEDB_PIN, PIN_MODE_OUTPUT_NOPULL);

    return 0;
}
//INIT_BOARD_EXPORT(rt_hw_gpio_led_init);





/**
 * @desc  :  PWM输出管脚初始化配置
 * @param : htim 定时器句柄
 * @return: None
 * @date  : 2017-8-13 09:05:02
 */
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
    if (htim->Instance == TIM5)
    {
        __HAL_RCC_TIM5_CLK_ENABLE();  /* 定时器时钟使能 */
        __HAL_RCC_GPIOH_CLK_ENABLE(); /* 开启GPIO时钟*/
        

        GPIO_Initure.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; /* */
        GPIO_Initure.Mode = GPIO_MODE_AF_PP;
        GPIO_Initure.Pull = GPIO_PULLUP;
        GPIO_Initure.Speed = GPIO_SPEED_HIGH;
        GPIO_Initure.Alternate = GPIO_AF2_TIM5; /* PH10-TIM5_CH1、PH11-TIM5_CH2、PH12-TIM5_CH3 */
        HAL_GPIO_Init(GPIOH, &GPIO_Initure);
			
        HAL_TIM_Base_Start_IT(htim);/* 启动定时器中断*/
        HAL_NVIC_SetPriority(TIM5_IRQn, 0, 0);/* NVIC配置*/
        HAL_NVIC_EnableIRQ(TIM5_IRQn);
    }
}
/**
 * @desc  : PWM输出缺省配置
 * @param : htim 定时器句柄
 * @return: None
 * @date  : 2017-8-14 08:57:37
 */
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
    if (htim->Instance == TIM5)
    {
        __HAL_RCC_TIM5_CLK_DISABLE(); /* 关闭TIM5时钟*/
        HAL_NVIC_DisableIRQ(TIM5_IRQn);
    }
}
/**
 * @desc  : 通用定时器的初始化并配置PWM通道
 * @param : None
 * @return: None
 * @date  : 2017-8-13 08:11:05
 */
static int rt_hw_pwm_output_init(void)
{
    TIM_ClockConfigTypeDef sClockSourceConfig;
    TIM_MasterConfigTypeDef sMasterConfig;
    TIM_OC_InitTypeDef sConfigOC;

    htimx.Instance = TIM5;       /* 定时器选择*/
    htimx.Init.Prescaler = (10-1); /* 计数器的分频值*/
    htimx.Init.CounterMode = TIM_COUNTERMODE_UP;    /* 计数模式*/
    htimx.Init.Period = (512-1);         /* 自动重装载值,该值必须和pwm表中最大值相吻合*/
    htimx.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&htimx);/* 此函数中会回调 HAL_TIM_PWM_MspInit()*/

    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;  /* 配置定时器时钟源*/
    HAL_TIM_ConfigClockSource(&htimx, &sClockSourceConfig);
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;         /* TIM输入输出复位*/
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;/* 关闭从控制模式*/
    HAL_TIMEx_MasterConfigSynchronization(&htimx, &sMasterConfig);

    sConfigOC.OCMode = TIM_OCMODE_PWM1;       /* PWM模式1 模式说明参考:《1-STM32F4xx中文参考手册1》 P.433*/
    sConfigOC.Pulse = 0;                      /* 初始占空比为0*/
    sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;/* 当计数器值小于CCR1_Val 时输出低电平,LED亮*/
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;/* 不启用快速输出模式*/
    HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_1);
    HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_2);
    HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_3);
//    HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_4);

    HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_1); /* 启动通道1 此函数会启动定时器*/
    HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_2); /* 启动通道2*/
    HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_3); /* 启动通道3*/

    return 0;
}
INIT_BOARD_EXPORT(rt_hw_pwm_output_init);


__IO uint16_t period_class = 1;
uint16_t POINT_NUM = sizeof(indexWave) / sizeof(indexWave[0]);

/**
 * @desc  : 定时器中断回调函数
 * @param : htim 定时器句柄
 * @return: None
 * @date  : 2017-8-13 10:19:26
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    static uint16_t pwm_index = 0;        /* 用于PWM查表*/
    static uint16_t period_cnt = 0;       /* 用于计算周期数*/
    static uint16_t amplitude_cnt = 0;    /* 计算幅值等级*/
    amplitude_cnt++;
    /*每个PWM表中每个元素都有256 个等级没增加一级多输出一次脉冲,即PWM表中的元素多使用一次使用256次,根据RGB颜色分量设置通道输出*/
    if (amplitude_cnt > (256 - 1))
    {
        period_cnt++;
        if (period_cnt > period_class)  /* 每个PWM表中的每个元素使用 period_class 次 这个值越大表示pwm一个周期越长*/
        {
            period_cnt = 0;             /* 重置周期计数标志*/
            if ((pwm_index++) >=  POINT_NUM)/* 标志指向PWM表中的下一个元素*/
            {
                pwm_index = 0;/* 如果到PWM表尾，则重复指向表头*/
            } 
        }
        amplitude_cnt = 0;              /* 重置幅值计数标志*/
    }
    else
    {
        /* 红*/
        if (((LED_RGB_COLOR_GREEN & 0xFF0000) >> 16) >= amplitude_cnt)/* 根据RGB颜色分量值,设置各个通道是否输出当前的PWM表元素表示亮度*/
            htimx.Instance->CCR1 = indexWave[pwm_index];    /* 根据PWM表修改定时器的比较寄存器的值*/
        else
            htimx.Instance->CCR1 = 0;                       /* 比较寄存器的值为0，则通道输出高电平，该通道LED灯灭*/
        /* 绿*/
        if (((LED_RGB_COLOR_GREEN & 0x00FF00) >> 8) >= amplitude_cnt)
            htimx.Instance->CCR2 = indexWave[pwm_index];
        else
            htimx.Instance->CCR2 = 0;
        /* 蓝*/
        if ((LED_RGB_COLOR_GREEN & 0x0000FF) >= amplitude_cnt)
            htimx.Instance->CCR3 = indexWave[pwm_index];
        else
            htimx.Instance->CCR3 = 0;
    }
}
void TIM5_IRQHandler()
{
    HAL_TIM_IRQHandler(&htimx);
}
